package spms.data.service.impl;

import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.Alias;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import spms.data.dao.BaseDao;
import spms.data.service.BaseService;
import spms.data.util.Page;

@Service
public class BaseServiceImpl<T> implements BaseService<T> {
	Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	BaseDao<T> baseDao;


	@Override
	public int count(String tableName) {
		return baseDao.count(tableName);
	}

	@Override
	public List<T> findAll(Class<T> clazz) throws Exception{
		String value = clazz.getAnnotation(Alias.class).value().toLowerCase();
		if(StringUtils.isNotEmpty(value)){
			String tableName = value.toLowerCase();
			logger.info("开始调用findAll(Class<T> clazz)查询表：{}",tableName);
			List<T> result = baseDao.findAll(null,value);
			result = parseResult(result,clazz);
			logger.info("调用findAll(Class<T> clazz)查询表：{} ，查询结束，返回：{}",tableName,result);
			return result;
		}
		throw new Exception("the entity object"+clazz.getName()+" has no alias name," +
				"this name must be same with the target table name(case insensitive)");
	}

	@Override
	public List<T> findAll(T t) throws Exception {
		Alias alias = t.getClass().getAnnotation(Alias.class);
		if(StringUtils.isNotEmpty(alias.value())){
			StringBuffer sb = new StringBuffer();
			JSONObject job = JSONObject.parseObject(JSONObject.toJSONString(t));

			for(String key:job.keySet()){
				String val = parseParam(job.get(key));
				sb.append(key.toLowerCase()+"="+val+" and");
			}
			String sql = sb.length()>3 ? sb.substring(0,sb.length()-3) : null;
			logger.info("开始调用findAll(T t)查询表：{}",alias.value().toLowerCase());
			List<T> result = baseDao.findAll(sql,alias.value().toLowerCase());
			result = parseResult(result,t.getClass());
			logger.info("调用findAll(T t)查询表：{} ，查询结束，返回：{}",alias.value().toLowerCase(),result);
			return result;
		}
		throw new Exception("the entity object"+t.getClass().getName()+" has no alias name," +
				"this name must be same with the target table name(case insensitive)");

	}

	@Override
	public Page<T> findPage(int pageNum, int pageSize,Class<T> clazz) throws Exception{
		Alias alias = clazz.getAnnotation(Alias.class);
		if(StringUtils.isNotEmpty(alias.value())){
			logger.info("开始调用findPage(int pageNum, int pageSize,Class<T> clazz)查询表：{}",alias.value().toLowerCase());
			List<T> result = baseDao.findPage(pageNum,pageSize,alias.value().toLowerCase());
			result = parseResult(result,clazz);
			logger.info("调用findPage(int pageNum, int pageSize,Class<T> clazz)查询表：{} ，查询结束，返回：{}",alias.value().toLowerCase(),result);
			return new Page<T>(pageNum,pageSize,count(alias.value().toLowerCase()),result);
		}
		throw new Exception("the entity object"+clazz.getName()+" has no alias name," +
				"this name must be same with the target table name(case insensitive)");
	}

	public String parseParam(Object obj){
		if(obj instanceof String){
			return "'"+obj+"'";
		}else if(obj instanceof Integer){
			return obj.toString();
		}else if(obj instanceof Date){
			return "'"+new SimpleDateFormat("yyyy-MM-dd").format((Date)obj)+"'";
		}else if(obj instanceof Timestamp){
			return "'"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Timestamp)obj)+"'";
		}

		return null;
	}

	public List<T> parseResult(List<T> result, Class<?> clazz){
		List<T> list = new ArrayList<>();
		List<Field> fields = Arrays.asList(clazz.getDeclaredFields());

		result.forEach(item ->{
			Map map = (HashMap)item;
			Map temp = new HashMap();

			fields.forEach(field -> {
				String name = field.getName();
				if(map.containsKey(name.toLowerCase())){
					temp.put(name,map.get(name.toLowerCase()));
				}else{
					temp.put(name,null);
				}
			});
			list.add((T)temp);
		});
		return list;
	}

}
